/**
 * PHOSIDE: PHosphorylation Site IDentification Engine.
 * Copyright 2009 Digital Biology Lab, University of Missouri.
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 3 of the License, or (at your option) any later
 * version. <p/> This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more
 * details.
 */

package phoside.classify;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import phoside.data.feature.extaction.AminoAcidFrequencyFeatureExtractor;
import phoside.data.feature.model.Instance;
import phoside.data.feature.model.InstanceUtil;

import phoside.util.ProteinSequenceUtil;
import phoside.util.SortUtil;

/**
 *
 * @author gjj
 */
public class FrequencyFeatureExtractorTrainingDataChangeHandler implements TrainingDataChangeHandler {
    protected final AminoAcidFrequencyFeatureExtractor frequencyFeatureExtractor;
    protected final int numberFrequencyFeatures;
    protected final int windowOffset;

    public FrequencyFeatureExtractorTrainingDataChangeHandler(
            final AminoAcidFrequencyFeatureExtractor frequencyFeatureExtractor,
            final int numberFrequencyFeatures,
            final int windowOffset) {
        this.frequencyFeatureExtractor = frequencyFeatureExtractor;
        this.numberFrequencyFeatures = numberFrequencyFeatures;
        this.windowOffset = windowOffset;
    }

    public void trainingDataChanged(List<Instance> instances, List<Double> label) {
        int n = instances.size();
        StringBuilder sbpos = new StringBuilder(n*(2*windowOffset+1));
        StringBuilder sbneg = new StringBuilder(n*(2*windowOffset+1));
        for (int i=0; i<n; i++) {
            String sequence = InstanceUtil.extractSurroundingSequence(instances.get(i), windowOffset);
            if (sequence!=null) {
                StringBuilder sb = new StringBuilder(sequence.toUpperCase());
                sb.deleteCharAt(windowOffset); // remove the center
                if (label.get(i)==1) {
                    sbpos.append(sb);
                } else {
                    sbpos.append(sb);
                }
            }
        }     
        
        Map<Character,Double> frePos = ProteinSequenceUtil.aminoAcidFrequencies(sbpos.toString());
        Map<Character,Double> freNeg = ProteinSequenceUtil.aminoAcidFrequencies(sbneg.toString());

        Set<Character> aas = new HashSet(20);
        aas.addAll(frePos.keySet());
        aas.addAll(freNeg.keySet());

        List<Character> list = new ArrayList(aas);

        final double eps = 10e-10;

        int nl = aas.size();
        List<Double> freScore = new ArrayList(nl);
        for (int i=0; i<nl; i++) {
            Character aa = list.get(i);

            double pos = frePos.get(aa);
            if (pos==0)
                pos += eps;

            double neg = freNeg.get(aa);
            if (neg==0)
                neg += eps;

            freScore.add(Math.abs(Math.log(pos)-Math.log(neg)));
        }

        List<Integer> idx = SortUtil.sortList(freScore, false);

        StringBuilder alphabet = new StringBuilder();
        for (int i=0; i<numberFrequencyFeatures; i++) {
            alphabet.append(list.get(idx.get(i)));
        }

        frequencyFeatureExtractor.setAminoAcidAlphabet(alphabet.toString());
    }
}
